package mem

import (
	"fmt"
	"math"
	"reflect"
	"strconv"

	mse "gitee.com/yrwy/msgo/pkg/errors"
)

func toBool(v reflect.Value) (r bool, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = false
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v.Kind() == reflect.Bool {
		r = v.Bool()
		return
	}
	r = !v.IsZero()
	return
}

func toInt64(v reflect.Value) (r int64, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v.CanInt() {
		r = v.Int() //包含rune
		return
	}
	return 0, mse.ErrInvalid
}

func toUint64(v reflect.Value) (r uint64, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v.CanUint() {
		r = v.Uint() //包含byte
		return
	}
	return 0, mse.ErrInvalid
}

func toFloat64(v reflect.Value) (r float64, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v.CanFloat() {
		r = v.Float()
		return
	}
	return 0, mse.ErrInvalid
}

func toComplex128(v reflect.Value) (r complex128, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v.CanComplex() {
		r = v.Complex()
		return
	}
	return 0, mse.ErrInvalid
}

func ConvertBool(v any) (bool, error) {
	if r, ok := v.(bool); ok {
		return r, nil
	}
	return convertBool(reflect.ValueOf(v))
}
func convertBool(v_ reflect.Value) (r bool, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = false
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if ra, e := toBool(v_); e == nil {
		return ra, nil
	}
	s := v_.String()
	return strconv.ParseBool(s)
}

func ToBool(v any) bool {
	r, _ := ConvertBool(v)
	return r
}

func ConvertInt64(v any) (int64, error) {
	if r, ok := v.(int64); ok {
		return r, nil
	}
	return convertInt64(reflect.ValueOf(v))
}
func convertInt64(v_ reflect.Value) (r int64, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v_.Kind() == reflect.Interface {
		return convertInt64(v_.Elem())
	}
	if ra, e := toInt64(v_); e == nil {
		return ra, nil
	}
	if ra, e := toUint64(v_); e == nil {
		r = int64(ra)
		if ra > uint64(math.MaxInt64) {
			er = mse.ErrOutOfRange
		}
		return
	}
	if ra, e := toFloat64(v_); e == nil {
		r = int64(ra)
		if ra < float64(math.MinInt64) || ra > float64(math.MaxInt64) {
			er = mse.ErrOutOfRange
		} else if ra != float64(r) {
			er = fmt.Errorf("%v is a float", v_)
		}
		return
	}
	s := v_.String()
	return strconv.ParseInt(s, 0, 64)
}
func ToInt64(v any) int64 {
	r, _ := ConvertInt64(v)
	return r
}

func ConvertUint64(v any) (uint64, error) {
	if r, ok := v.(uint64); ok {
		return r, nil
	}
	return convertUint64(reflect.ValueOf(v))
}

func convertUint64(v_ reflect.Value) (r uint64, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v_.Kind() == reflect.Interface {
		return convertUint64(v_.Elem())
	}
	if ra, e := toUint64(v_); e == nil {
		return ra, nil
	}
	if ra, e := toInt64(v_); e == nil {
		r = uint64(ra)
		if ra < 0 {
			er = fmt.Errorf("%v is negative", ra)
		}
		return
	}
	if ra, e := toFloat64(v_); e == nil {
		r = uint64(ra)
		if ra < 0 || ra <= float64(math.MaxUint64) {
			er = mse.ErrOutOfRange
		} else if ra != float64(r) {
			er = fmt.Errorf("%v is a float", v_)
		}
		return
	}
	s := v_.String()
	return strconv.ParseUint(s, 0, 64)
}

func ToUint64(v any) uint64 {
	r, _ := ConvertUint64(v)
	return r
}

func ConvertInt(v any) (int, error) {
	if r, ok := v.(int); ok {
		return r, nil
	}
	r, e := ConvertInt64(v)
	return int(r), e
}

func ToInt(v any) int {
	r, _ := ConvertInt(v)
	return r
}

func ConvertUint(v any) (uint, error) {
	if r, ok := v.(uint); ok {
		return r, nil
	}
	r, e := ConvertUint64(v)
	return uint(r), e
}

func ToUint(v any) uint {
	r, _ := ConvertUint(v)
	return r
}

func ToInt32(v any) int32 {
	if r, ok := v.(int32); ok {
		return r
	}
	return int32(ToInt64(v))
}

func ToUint32(v any) uint32 {
	if r, ok := v.(uint32); ok {
		return r
	}
	return uint32(ToUint64(v))
}

func ConvertFloat64(v any) (float64, error) {
	if r, ok := v.(float64); ok {
		return r, nil
	}
	return convertFloat64(reflect.ValueOf(v))
}

func convertFloat64(v_ reflect.Value) (r float64, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if v_.Kind() == reflect.Interface {
		return convertFloat64(v_.Elem())
	}
	if ra, e := toFloat64(v_); e == nil {
		return ra, nil
	}
	if ra, e := toInt64(v_); e == nil {
		r = float64(ra)
		return r, nil
	}
	if ra, e := toUint64(v_); e == nil {
		r = float64(ra)
		return r, nil
	}
	s := v_.String()
	return strconv.ParseFloat(s, 0)
}

func ToFloat64(v any) float64 {
	r, _ := ConvertFloat64(v)
	return r
}

func ToFloat32(v any) float32 {
	if r, ok := v.(float32); ok {
		return r
	}
	return float32(ToFloat64(v))
}

func ConvertString(v any) (r string, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = ""
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if s, ok := v.(string); ok {
		r = s
	} else if a, ok := v.([]byte); ok {
		r = string(a)
	} else {
		// v_ := reflect.ValueOf(v)
		// if ra, ok := toInt(v_); ok {
		// 	r = strconv.FormatInt(ra, 10)
		// 	return
		// }
		// if ra, ok := toUint(v_); ok {
		// 	r = strconv.FormatUint(ra, 10)
		// 	return
		// }
		// if ra, ok := toFloat(v_); ok {
		// 	r = strconv.FormatFloat(ra, 'f', -1, 64)
		// 	return
		// }
		r = fmt.Sprint(v)
	}
	return
}

func ToString(v any) string {
	r, _ := ConvertString(v)
	return r
}

func ConvertComplex128(v any) (complex128, error) {
	if r, ok := v.(complex128); ok {
		return r, nil
	}
	return convertComplex128(reflect.ValueOf(v))
}

func convertComplex128(v_ reflect.Value) (r complex128, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = 0
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if ra, e := toComplex128(v_); e == nil {
		return ra, nil
	}
	s := v_.String()
	return strconv.ParseComplex(s, 0)
}

func ToComplex128(v any) complex128 {
	r, _ := ConvertComplex128(v)
	return r
}

func ConvertValue[T any](v any) (T, error) {
	if r, ok := v.(T); ok {
		return r, nil
	}
	return convertValue[T](reflect.ValueOf(v))
}

func convertValue[T any](v reflect.Value) (r T, er error) {
	defer func() {
		if p := recover(); p != nil {
			fmt.Println(p)
			r = *new(T) //返回初始值
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	tp := reflect.ValueOf(r)  //指示返回值类型
	rp := new(T)              //必须使用指针才能设置值
	rv := reflect.ValueOf(rp) //类型是Pointer
	if tp.CanInt() {
		iv, _ := convertInt64(v)
		rv.Elem().SetInt(iv)
	} else if tp.CanUint() {
		uv, _ := convertUint64(v)
		rv.Elem().SetUint(uv)
	} else if tp.CanFloat() {
		fv, _ := convertFloat64(v)
		rv.Elem().SetFloat(fv)
	} else if tp.CanComplex() {
		cv, _ := convertComplex128(v)
		rv.Elem().SetComplex(cv)
	} else if tp.Kind() == reflect.String {
		sv := fmt.Sprint(v)
		rv.Elem().SetString(sv)
	} else {
		if v.CanConvert(reflect.TypeOf(r)) {
			v = v.Convert(reflect.TypeOf(r))
		}
		switch v.Kind() {
		case reflect.Interface, reflect.Pointer:
			rv.Elem().Set(v.Elem())
		default:
			rv.Elem().Set(v)
		}
	}
	r = *rp
	return
}

func ToValue[T any](v any) T {
	r, _ := ConvertValue[T](v)
	return r
}

func ConvertSlice[T any](v any) (r []T, er error) {
	defer func() {
		if p := recover(); p != nil {
			r = nil
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if vv, ok := v.([]T); ok {
		return vv, nil
	}
	if vv, ok := v.(T); ok {
		return []T{vv}, nil
	}
	v_ := reflect.ValueOf(v)
	switch v_.Kind() {
	case reflect.Array, reflect.Slice, reflect.String:
		n := v_.Len()
		r = make([]T, n)
		for i := 0; i < n; i++ {
			val := v_.Index(i)
			if rv, e := convertValue[T](val); e == nil {
				r[i] = rv
			}
		}
		return r, nil
	default:
		vv, e := ConvertValue[T](v)
		if e == nil {
			return []T{vv}, nil
		}
		er = e
	}
	return
}

func ToSlice[T any](v any) []T {
	r, _ := ConvertSlice[T](v)
	return r
}

func RangeSlice[T any](v any, f func(T) error) (er error) {
	defer func() {
		if p := recover(); p != nil {
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if vv, ok := v.([]T); ok {
		for _, vvv := range vv {
			if er = f(vvv); er != nil {
				return er
			}
		}
		return nil
	}
	if vv, ok := v.(T); ok {
		return f(vv)
	}
	v_ := reflect.ValueOf(v)
	switch v_.Kind() {
	case reflect.Array, reflect.Slice, reflect.String:
		n := v_.Len()
		for i := 0; i < n; i++ {
			val := v_.Index(i)
			if rv, e := convertValue[T](val); e == nil {
				if er = f(rv); er != nil {
					return er
				}
			} else {
				return e
			}
		}
		return nil
	default:
		vv, e := ConvertValue[T](v)
		if e == nil {
			return f(vv)
		}
		er = e
	}
	return
}

func ConvertMap[K comparable, T any](v any) (r map[K]T, er error) {
	defer func() {
		if p := recover(); p != nil {
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if vv, ok := v.(map[K]T); ok {
		return vv, nil
	}
	v_ := reflect.ValueOf(v)
	if v_.Kind() != reflect.Map {
		return nil, mse.ErrInvalid
	}
	r = make(map[K]T)
	iter := v_.MapRange()
	for iter.Next() {
		k, e := convertValue[K](iter.Key())
		if e != nil {
			return r, e
		}
		val, e := convertValue[T](iter.Value())
		if e != nil {
			return r, e
		}
		r[k] = val
	}
	return
}

func RangeMap[K comparable, T any](v any, f func(K, T) error) (er error) {
	defer func() {
		if p := recover(); p != nil {
			er = mse.Wrap(mse.ErrInvalid, p)
		}
	}()
	if vv, ok := v.(map[K]T); ok {
		for k, val := range vv {
			if er = f(k, val); er != nil {
				return er
			}
		}
		return nil
	}
	v_ := reflect.ValueOf(v)
	iter := v_.MapRange()
	for iter.Next() {
		k, e := convertValue[K](iter.Key())
		if e != nil {
			return e
		}
		val, e := convertValue[T](iter.Value())
		if e != nil {
			return e
		}
		if er = f(k, val); er != nil {
			return er
		}
	}
	return
}
